package com.easylinkin.linkappapi.safe.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.safe.dao.HiddenDangerMapper;
import com.easylinkin.linkappapi.safe.dao.InspectionPlanMapper;
import com.easylinkin.linkappapi.safe.dao.InspectionTaskMapper;
import com.easylinkin.linkappapi.safe.dto.HiddenDangerDTO;
import com.easylinkin.linkappapi.safe.dto.InspectionTaskDTO;
import com.easylinkin.linkappapi.safe.entity.HiddenDanger;
import com.easylinkin.linkappapi.safe.entity.InspectionPlan;
import com.easylinkin.linkappapi.safe.entity.InspectionTask;
import com.easylinkin.linkappapi.safe.service.InspectionTaskService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.security.mapper.LinkappUserMapper;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 自检任务表 服务实现类
 * </p>
 *
 * @author TongJie
 * @since 2022-04-13
 */
@Service
public class InspectionTaskServiceImpl extends
    ServiceImpl<InspectionTaskMapper, InspectionTask> implements InspectionTaskService {

  @Resource
  private LinkappUserContextProducer linkappUserContextProducer;
  @Autowired
  private HiddenDangerMapper hiddenDangerMapper;
  @Autowired
  private LinkappUserMapper linkappUserMapper;
  @Autowired
  private InspectionPlanMapper inspectionPlanMapper;

  /**
   * 增加
   * @param inspectionTask
   */
  @Override
  public void insert(InspectionTask inspectionTask) {
    /**
     * 验证重复
     */
//    this.checkExist(inspectionTask);
    //设置基本属性
    this.setBase(inspectionTask);
    this.save(inspectionTask);
  }

  /**
   * 根据id编辑
   * @param inspectionTask
   */
  @Override
  public void updateOne(InspectionTask inspectionTask) {
    /**
     * 验证重复
     */
    this.checkExist(inspectionTask);
    //设置基本属性
    this.setBase(inspectionTask);
    this.updateById(inspectionTask);
  }

  @Override
  public IPage<InspectionTaskDTO> queryList(RequestModel<InspectionTaskDTO> requestModel) {
    Page page = requestModel.getPage();
    InspectionTaskDTO inspectionTaskDTO = requestModel.getCustomQueryParams();
    inspectionTaskDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    IPage<InspectionTaskDTO> iPage = baseMapper.queryListByPage(page, inspectionTaskDTO);
    //组织名称类型
    //组织检查记录/隐患相关数据
    List<Integer> ids = iPage.getRecords().stream().map(i -> i.getId())
        .collect(Collectors.toList());
    if (ids.size() > 0){
      //查询账户列表备用
      QueryWrapper<LinkappUser> userQueryWrapper = new QueryWrapper<>();
      userQueryWrapper.eq("tenant_id",linkappUserContextProducer.getNotNullCurrent().getTenantId());
      List<LinkappUser> users = linkappUserMapper.selectList(userQueryWrapper);
      //查询所有相关的检查记录/隐患
      QueryWrapper<HiddenDanger> dangerQueryWrapper = new QueryWrapper<>();
      dangerQueryWrapper.in("task_id_",ids);
      List<HiddenDanger> dangerList = hiddenDangerMapper.selectList(dangerQueryWrapper);
      iPage.getRecords().forEach(i->{
        //创建人
        List<LinkappUser> collect = users.stream().filter(u -> u.getId().equals(i.getCreatorId()))
            .collect(Collectors.toList());
        i.setCreatorName(collect.get(0).getNickname());
        //计划检查人
        i.setPlanUsers(getUserNames(users, i.getUserIds()));
        List<HiddenDanger> list = dangerList.stream()
            .filter(d -> i.getId().equals(d.getTaskId()))
            .sorted(Comparator.comparing(HiddenDanger::getCreateTime))
            .collect(Collectors.toList());
        if (list.size()>0){
          i.setActTime(list.get(0).getCreateTime());
          long count1 = list.stream().filter(l -> Integer.valueOf(1).equals(l.getType())).count();
          i.setDangerNum((int)count1);
          long count2 = list.stream().filter(l -> Integer.valueOf(2).equals(l.getType())).count();
          i.setCheckNum((int)count2);
          //实际检查人
          List<Long> userIds2 = list.stream().map(l -> l.getCreateUid())
              .collect(Collectors.toList());
          i.setActUsers(getUserNames(users, userIds2));
        }
      });
    }
    return iPage;
  }

  @Override
  public InspectionTaskDTO findById(Integer id) {
    InspectionTaskDTO inspectionTaskDTO = new InspectionTaskDTO();
    //查询单个详情
    InspectionTaskDTO inspectionTask = new InspectionTaskDTO();
    inspectionTask.setId(id);
    RequestModel<InspectionTaskDTO> requestModel = new RequestModel<>();
    requestModel.setCustomQueryParams(inspectionTask);
    Page page = new Page();
    page.setCurrent(1);
    page.setSize(-1);
    requestModel.setPage(page);
    List<InspectionTaskDTO> list = this.queryList(requestModel).getRecords();
    if (list.size() > 0){
      inspectionTaskDTO = list.get(0);
      //查询巡检记录
      HiddenDangerDTO hiddenDangerDTO = new HiddenDangerDTO();
      hiddenDangerDTO.setTaskId(id);
      IPage<HiddenDangerDTO> dangerDTOIPage = hiddenDangerMapper
          .selectListByPage(page, hiddenDangerDTO);
      inspectionTaskDTO.setHiddenDangers(dangerDTOIPage.getRecords());
    }
    return inspectionTaskDTO;
  }

  @Override
  public void computeStatus(Integer id) {
    InspectionTask inspectionTask = baseMapper.selectById(id);
    //查询下面的排查或者隐患
    QueryWrapper<HiddenDanger> hQueryWrapper = new QueryWrapper<>();
    hQueryWrapper.eq("task_id_",id).orderByAsc("create_time");
    List<HiddenDanger> hiddenDangers = hiddenDangerMapper.selectList(hQueryWrapper);
    if (hiddenDangers.size() > 0){
      inspectionTask.setStatus(2);
    }else {
      inspectionTask.setStatus(1);
    }
    baseMapper.updateById(inspectionTask);
    //计算任务计划的状态
    computePlanStatus(inspectionTask);
  }

  private void computePlanStatus(InspectionTask inspectionTask) {
    QueryWrapper<InspectionTask> taskWrapper = new QueryWrapper<>();
    taskWrapper.eq("plan_id_",inspectionTask.getPlanId());
    List<InspectionTask> inspectionTasks = baseMapper.selectList(taskWrapper);
    if (inspectionTasks.size() > 0){
      int status = 1;
      long count1 = inspectionTasks.stream().filter(i -> Integer.valueOf(1).equals(i.getStatus()))
          .count();
      long count2 = inspectionTasks.stream().filter(i -> Integer.valueOf(2).equals(i.getStatus()))
          .count();
      if (count1 == inspectionTasks.size()){
        status = 1;
      }else if (count2 == inspectionTasks.size()){
        status = 3;
      }else {
        status =2;
      }
      //更新计划状态
      UpdateWrapper<InspectionPlan> updateWrapper = new UpdateWrapper<>();
      updateWrapper.set("status_",status).eq("id",inspectionTask.getPlanId());
      inspectionPlanMapper.update(null,updateWrapper);
    }
  }

  //生成任务项
  @Override
  public void insertByPlan(InspectionPlan inspectionPlan, Boolean flag) {
    //判断当天是不是周期开始时间
    Date time = inspectionPlan.getStartTime();
    if (DateUtil.beginOfDay(new Date()).getTime() == time.getTime() || !flag){
      //判断当天有没有生成，有不生成。无生成
      QueryWrapper<InspectionTask> queryWrapper = new QueryWrapper<>();
      queryWrapper.eq("plan_id_",inspectionPlan.getId())
          .eq("start_time_",DateUtil.beginOfDay(new Date()));
      Integer integer = baseMapper.selectCount(queryWrapper);
      if (integer <1){
        //生成
        InspectionTask inspectionTask = new InspectionTask();
        inspectionTask.setPlanId(inspectionPlan.getId());
        inspectionTask.setTenantId(inspectionPlan.getTenantId());
        inspectionTask.setStatus(1);
        inspectionTask.setStartTime(DateUtil.beginOfDay(new Date()));
        //判断是月度还是定期
        if (Integer.valueOf(1).equals(inspectionPlan.getType())){
          inspectionTask.setEndTime(
              DateUtil.endOfWeek(new Date()).getTime()>inspectionPlan.getEndTime().getTime()?inspectionPlan.getEndTime():DateUtil.endOfWeek(new Date()).offset(DateField.MILLISECOND, -999));
        }else {
          inspectionTask.setEndTime(
              DateUtil.endOfMonth(new Date()).getTime()>inspectionPlan.getEndTime().getTime()?inspectionPlan.getEndTime():DateUtil.endOfMonth(new Date()).offset(DateField.MILLISECOND, -999));
        }
        this.insert(inspectionTask);
        //计算计划状态
        this.computePlanStatus(inspectionTask);
      }
    }
  }

  /**
   * 通过userid字符串获取userNames
   * @param users
   * @param userIds
   * @return
   */
  private String getUserNames(List<LinkappUser> users, Object userIds) {
    String userNames = null;
    List<Integer> userList = new ArrayList<>();
    if (userIds instanceof String && StringUtils.isNotBlank((String)userIds)){
      String[] split = ((String) userIds).split(",");
      for (int i = 0; i < split.length; i++) {
        userList.add(Integer.valueOf(split[i]));
      }
    }else if (userIds instanceof List){
      userList = (List)userIds;
    }
    List<Integer> finalUserList = userList;
    List<String> stringList = users.stream().filter(u -> finalUserList.contains(u.getId().intValue()) || finalUserList.contains(u.getId()))
        .map(u -> u.getNickname())
        .collect(Collectors.toList());
    if (stringList.size() > 0){
      userNames = StringUtils.join(stringList, ",");
    }
    return userNames;
  }

  @Override
  public IPage<InspectionTaskDTO> queryListByPage(RequestModel<InspectionTaskDTO> requestModel) {
    Page page = requestModel.getPage();
    InspectionTaskDTO inspectionTaskDTO = requestModel.getCustomQueryParams();
    //项目id 过滤
    inspectionTaskDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    IPage<InspectionTaskDTO> inspectionTaskIPage = baseMapper.queryListByPage(page, inspectionTaskDTO);
    return inspectionTaskIPage;
  }

  /**
   * 验证重复
   */
  private void checkExist(InspectionTask inspectionTask) {
    QueryWrapper<InspectionTask> queryWrapper = new QueryWrapper<>();
    //todo 设置判断重复条件
    //编辑的时候存在id
    Optional.ofNullable(inspectionTask.getId()).ifPresent(id -> queryWrapper.ne("id",inspectionTask.getId()));
    Integer integer = baseMapper.selectCount(queryWrapper);
    if (integer>0){
      throw new BusinessException("该自检任务已存在");
    }
  }

  /**
   * 设置基本属性
   * @param inspectionTask
   */
  private void setBase(InspectionTask inspectionTask) {
    inspectionTask.setModifyTime(new Date());
    if (null != linkappUserContextProducer.getCurrent()){
      inspectionTask.setModifyId(linkappUserContextProducer.getCurrent().getId());
    }
    //没有id就是新增,有就是编辑
    if (null == inspectionTask.getId()){
      if (null != linkappUserContextProducer.getCurrent()){
        inspectionTask.setCreatorId(linkappUserContextProducer.getCurrent().getId());
      }
      inspectionTask.setCreateTime(new Date());
      if (StringUtils.isBlank(inspectionTask.getTenantId())){
        inspectionTask.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
      }
    }
  }
}
